﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace Hands.Unit.Web
{
    internal class Http : IHttp
    {
        private static readonly List<string> contentType = new List<string>
        {
            "application/json",
            "text/xml",
            "text/plain"
        };

        private const string UTF8 = "UTF-8";

        private const string GET = "GET";
        private const string PUT = "PUT";
        private const string DELETE = "DELETE";
        private const string POST = "POST";

        private WebRequest request = null;

        /// <summary>
        /// 向指定url发送post请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="content">post请求的参数</param>
        /// <param name="contentType">post请求参数的类型</param>
        /// <returns>请求返回值</returns>
        /// <exception cref="">NotImplementedException</exception>
        /// <exception cref="">ResponseException</exception>
        public string post(string url, string content, ContentType type)
        {
            byte[] data = Encoding.GetEncoding("UTF-8").GetBytes(content);

            request = WebRequest.Create(url);

            clearReuqestHeader();

            addRequestHeaders(type, data);

            request.Method = POST;

            return getResponseData();
        }

        /// <summary>
        /// 向指定url发送get请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <returns>请求返回结果</returns>
        /// <exception cref="">NotImplementedException</exception>
        /// <exception cref="">ResponseException</exception>
        public string get(string url)
        {
            request = WebRequest.Create(url);

            clearReuqestHeader();

            request.Method = POST;

            return getResponseData();
        }

        /// <summary>
        /// 向指定地址发送put请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="content">请求参数</param>
        /// <param name="type">请求参数类型</param>
        /// <returns>请求返回结果</returns>
        /// <exception cref="">NotImplementedException</exception>
        /// <exception cref="">ResponseException</exception>
        public string put(string url, string content, ContentType type)
        {
            byte[] data = Encoding.GetEncoding("UTF-8").GetBytes(content);

            request = WebRequest.Create(url);

            clearReuqestHeader();

            addRequestHeaders(type, data);

            request.Method = PUT;

            return getResponseData();

        }

        /// <summary>
        /// 向指定的url发送delete请求
        /// </summary>
        /// <param name="url">url地址</param>
        /// <returns>请求返回结果</returns>
        /// <exception cref="">NotImplementedException</exception>
        /// <exception cref="">ResponseException</exception>
        public string delete(string url)
        {
            request = WebRequest.Create(url);

            clearReuqestHeader();

            request.Method = DELETE;

            return getResponseData();
        }

        //清除header
        private void clearReuqestHeader()
        {
            if (request.Headers.Count > 0)
            {
                request.Headers.Clear();
            }
        }

        //添加header
        private void addRequestHeaders(ContentType type, byte[] data)
        {
            request.Headers.Add("Content-Type", contentType[(int)type]);
            request.Headers.Add("ContentLength", data.Length.ToString());
        }

        //获取请求返回值
        private string getResponseData()
        {
            HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
            if (webResponse.StatusCode == HttpStatusCode.OK)
            {
                Stream result = webResponse.GetResponseStream();
                StreamReader reader = new StreamReader(result, Encoding.UTF8);
                return reader.ReadToEnd();
            }
            else
            {
                throw new ResponseException(webResponse.StatusCode.ToString());
            }
        }
    }
}
